home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / textual / tex / files / !tex / TeXsource / commontex / c / scan < prev    next >
Encoding:
Text File  |  1988-04-18  |  26.9 KB  |  854 lines

  1. /*
  2.  *    Copyright 1986, 1987 Pat Joseph Monardo. All rights reserved.
  3.  *    Copying of this file is granted according to the provisions 
  4.  *    specified in the file COPYING which must accompany this file.
  5.  */
  6.  
  7.  
  8. /*
  9.  *              scan.c
  10.  */
  11.  
  12. #include        "tex.h"
  13. #include        "cmds.h"
  14. #include        "heap.h"
  15. #include        "arith.h"
  16. #include        "eq.h"
  17. #include        "token.h"
  18. #include        "tokenstack.h"
  19. #include        "tokenlists.h"
  20. #include        "evalstack.h"
  21. #include        "char.h"
  22. #include        "str.h"
  23. #include        "box.h"
  24. #include        "tfm.h"
  25. #include        "dvi.h"
  26. #include        "print.h"
  27. #include        "error.h"
  28. #include        "page.h"
  29. #include        "scan.h"
  30.  
  31. gord    cur_order;
  32. val             cur_val;
  33. int             cur_val_level = INT_VAL;
  34. int             radix;
  35.  
  36. scan_left_brace ()
  37. {
  38.         get_nbrx_token();
  39.         if (cur_cmd != LEFT_BRACE) {
  40.                 print_err("Missing { inserted");
  41.                 help_left();
  42.                 back_error();
  43.                 cur_tok = LEFT_BRACE_TOKEN;
  44.                 cur_cmd = LEFT_BRACE;
  45.                 cur_chr= '{';
  46.                 incr(align_state);
  47.         }
  48. }
  49.  
  50. scan_optional_equals ()
  51. {
  52.         get_nbx_token();
  53.         if (cur_tok != OTHER_TOKEN + '=')
  54.                 back_input();
  55. }
  56.  
  57. bool
  58. scan_keyword (s)
  59.         char*   s;
  60. {
  61.         char    c;
  62.         ptr             p;
  63.         ptr             q;
  64.  
  65.         p = backup_tokens;
  66.         token_link(p) = NULL;
  67.         c = *s;
  68.         while (c != NUL) {
  69.                 get_x_token();
  70.                 if (cur_cs == 0 && (cur_chr == c || cur_chr == c - 'a' + 'A')) {
  71.                         store_new_token(cur_tok);
  72.                         incr(s);
  73.                         c = *s;
  74.                 } else if (cur_cmd != SPACER || p != backup_tokens) {
  75.                         back_input();
  76.                         if (p != backup_tokens)
  77.                                 back_list(token_link(backup_tokens));
  78.                         return FALSE;
  79.                 }
  80.         }
  81.         flush_list(token_link(backup_tokens));
  82.         return TRUE;
  83. }
  84.  
  85. mu_error ()
  86. {
  87.         print_err("Incompatible glue units");
  88.         help_mu_error();
  89.         error();
  90. }
  91.  
  92. #define scanned_result(CV, CVL) \
  93.         {cur_val = CV; cur_val_level = CVL;}
  94.  
  95. #define negate_glue() \
  96.         {width(cur_val) = -width(cur_val); \
  97.         stretch(cur_val) = -stretch(cur_val); \
  98.         shrink(cur_val) = -shrink(cur_val);}
  99.  
  100. scan_something_internal (level, negative)
  101.         int             level;
  102.         bool    negative;
  103. {
  104.         hword   m;
  105.         int             p;
  106.  
  107.         m = cur_chr;
  108.         switch (cur_cmd)
  109.         {
  110.         case DEF_CODE:
  111.                 scan_seven_bit_int();
  112.                 if (m == MATH_CODE_BASE)
  113.                         {scanned_result(ho(math_code(cur_val)), INT_VAL);}
  114.                 else if (m < MATH_CODE_BASE)
  115.                         {scanned_result(equiv(m + cur_val), INT_VAL);}
  116.                 else {scanned_result(eqtb[m + cur_val].i, INT_VAL);}
  117.                 break;
  118.  
  119.         case TOKS_REGISTER:
  120.         case ASSIGN_TOKS:
  121.         case DEF_FAMILY:
  122.         case SET_FONT:
  123.         case DEF_FONT:
  124.                 if (level != TOK_VAL) {
  125.                         print_err("Missing number, treated as zero");
  126.                         help_missing_number();
  127.                         back_error();
  128.                         scanned_result(0, DIMEN_VAL);
  129.                 } else if (cur_cmd <= ASSIGN_TOKS) {
  130.                         if (cur_cmd < ASSIGN_TOKS)  {
  131.                                 scan_eight_bit_int();
  132.                                 m = TOKS_BASE + cur_val;
  133.                         }
  134.                         scanned_result(equiv(m), TOK_VAL);
  135.                 } else {
  136.                         back_input();
  137.                         scan_font_ident();
  138.                         scanned_result(FONT_ID_BASE + cur_val, IDENT_VAL);
  139.                 }
  140.                 break;
  141.  
  142.         case ASSIGN_INT:
  143.                 scanned_result(eqtb[m].i, INT_VAL);
  144.                 break;
  145.  
  146.         case ASSIGN_DIMEN:
  147.                 scanned_result(eqtb[m].sc, DIMEN_VAL);
  148.                 break;
  149.  
  150.         case ASSIGN_GLUE:
  151.                 scanned_result(equiv(m), GLUE_VAL);
  152.                 break;
  153.         
  154.         case ASSIGN_MU_GLUE:
  155.                  scanned_result(equiv(m), MU_VAL);
  156.                  break;
  157.  
  158.         case SET_AUX:
  159.                 if (abs(mode) != m) {
  160.                         print_err("Improper ");
  161.                         print_cmd_chr(SET_AUX, m);
  162.                         help_aux();
  163.                         error();
  164.                         if (level != TOK_VAL)
  165.                                 {scanned_result(0, DIMEN_VAL);}
  166.                         else scanned_result(0, INT_VAL);
  167.                 } else {
  168.                         cur_val = aux; 
  169.                         if (m == VMODE)
  170.                                 cur_val_level = DIMEN_VAL;
  171.                         else cur_val_level = INT_VAL;
  172.                 }
  173.                 break;
  174.  
  175.         case SET_PREV_GRAF:
  176.                 nest[nest_ptr] = cur_list;
  177.                 p = nest_ptr;
  178.                 while (abs(nest[p].mode_field) != VMODE)
  179.                         decr(p);
  180.                 scanned_result(nest[p].pg_field, INT_VAL);
  181.                 break;
  182.  
  183.         case SET_PAGE_INT:
  184.                 if (m == 0)     
  185.                         cur_val = dead_cycles;
  186.                 else cur_val = insert_penalties;
  187.                 cur_val_level = INT_VAL;
  188.                 break;
  189.  
  190.         case SET_PAGE_DIMEN:
  191.                 if (page_contents == EMPTY)
  192.                         if (m == 0)
  193.                                 cur_val = MAX_DIMEN; 
  194.                         else cur_val = 0;
  195.                 else cur_val = page_so_far[m];
  196.                 cur_val_level = DIMEN_VAL;
  197.                 break;
  198.         
  199.         case SET_SHAPE:
  200.                 if (par_shape_ptr == NULL)
  201.                         cur_val = 0;
  202.                 else cur_val = info(par_shape_ptr);
  203.                 cur_val_level = INT_VAL;
  204.                 break;
  205.         
  206.         case SET_BOX_DIMEN:
  207.                 scan_eight_bit_int();
  208.                 if (box(cur_val) == NULL)
  209.                         cur_val = 0;
  210.                 else cur_val = mem[box(cur_val) + m].sc;
  211.                 cur_val_level = DIMEN_VAL;
  212.                 break;
  213.         
  214.         case CHAR_GIVEN:
  215.         case MATH_GIVEN:
  216.                 scanned_result(cur_chr, INT_VAL);
  217.                 break;
  218.         
  219.         case ASSIGN_FONT_DIMEN:
  220.                 find_font_dimen(FALSE);
  221.                 font_info[fmem_ptr].sc = 0;
  222.                 scanned_result(font_info[cur_val].sc, DIMEN_VAL); 
  223.                 break;
  224.         
  225.         case ASSIGN_FONT_INT:
  226.                 scan_font_ident();
  227.                 if (m == 0)
  228.                         {scanned_result(hyphen_char[cur_val], INT_VAL);}
  229.                 else scanned_result(skew_char[cur_val], INT_VAL);
  230.                 break;
  231.  
  232.         case REGISTER:
  233.                 scan_eight_bit_int();
  234.                 switch (m)
  235.                 {
  236.                 case INT_VAL:
  237.                         cur_val = count(cur_val);
  238.                         break;
  239.  
  240.                 case DIMEN_VAL:
  241.                         cur_val = dimen(cur_val);
  242.                         break;
  243.  
  244.                 case GLUE_VAL:
  245.                         cur_val = skip(cur_val);
  246.                         break;
  247.   
  248.                 case MU_VAL:
  249.                         cur_val = mu_skip(cur_val);
  250.                         break;
  251.                 }
  252.                 cur_val_level = m;
  253.                 break;
  254.  
  255.         case LAST_ITEM:
  256.                 if (cur_chr == GLUE_VAL)
  257.                         cur_val = zero_glue;
  258.                 else cur_val = 0;
  259.                 cur_val_level = cur_chr;
  260.                 if (!is_char_node(tail) && mode != 0) {
  261.                         switch (cur_chr)
  262.                         {
  263.                         case INT_VAL:
  264.                                 if (type(tail) == PENALTY_NODE)
  265.                                         cur_val = penalty(tail);
  266.                                 break;
  267.  
  268.                         case DIMEN_VAL:
  269.                                 if (type(tail) == KERN_NODE)
  270.                                         cur_val = width(tail);
  271.                                 break;
  272.  
  273.                         case GLUE_VAL:
  274.                                 if (type(tail) == GLUE_NODE) {
  275.                                         cur_val = glue_ptr(tail); 
  276.                                         if (subtype(tail) == MU_GLUE)
  277.                                                 cur_val_level = MU_VAL;
  278.                                 }
  279.                                 break;
  280.  
  281.                         default:
  282.                                 break;
  283.                         }
  284.                 } else if (mode == VMODE && tail == head) {
  285.                         switch (cur_chr)
  286.                         {
  287.                         case INT_VAL:
  288.                                 cur_val = last_penalty;
  289.                                 break;
  290.  
  291.                         case DIMEN_VAL:
  292.                                 cur_val = last_kern;
  293.                                 break;
  294.  
  295.                         case GLUE_VAL:
  296.                                 if (last_glue != MAX_HALFWORD)
  297.                                         cur_val = last_glue;
  298.                                 break;
  299.                         }
  300.                 }
  301.                 break;
  302.                         
  303.         default:
  304.                 print_err("You can't use `");
  305.                 print_cmd_chr(cur_cmd, cur_chr);
  306.                 print("' after ");
  307.                 print_esc("the");
  308.                 help_thee();
  309.                 error();
  310.                 if (level != TOK_VAL)
  311.                         {scanned_result(0, DIMEN_VAL);}
  312.                 else {scanned_result(0, INT_VAL);}
  313.                 break;
  314.         }
  315.         while (cur_val_level > level) {
  316.                 if (cur_val_level == GLUE_VAL)
  317.                         cur_val = width(cur_val);
  318.                 else if (cur_val_level == MU_VAL)
  319.                         mu_error();
  320.                 decr(cur_val_level);
  321.         }
  322.         if (negative) {
  323.                 if (cur_val_level >= GLUE_VAL) {
  324.                         cur_val = new_spec(cur_val);
  325.                         negate_glue();
  326.                 } else negate(cur_val);
  327.         } else if (cur_val_level >= GLUE_VAL && cur_val_level <= MU_VAL)
  328.                 add_glue_ref(cur_val);
  329. }
  330.  
  331. scan_seven_bit_int ()
  332. {
  333.         scan_int();
  334.         if (cur_val < 0 || cur_val > 127) {
  335.                 print_err("Bad character code");
  336.                 help_char_num();
  337.                 int_error(cur_val);
  338.                 cur_val = 0;
  339.         }
  340. }
  341.  
  342. scan_eight_bit_int ()
  343. {
  344.         scan_int();
  345.         if (cur_val < 0 || cur_val > 255) {
  346.                 print_err("Bad register code");
  347.                 help_reg();
  348.                 int_error(cur_val);
  349.                 cur_val = 0;
  350.         }
  351. }
  352.  
  353. scan_four_bit_int()
  354. {
  355.         scan_int();
  356.         if (cur_val < 0 || cur_val > 15) {
  357.                 print_err("Bad number");
  358.                 help_number();
  359.                 int_error(cur_val);
  360.                 cur_val = 0;
  361.         }
  362. }
  363.  
  364. scan_char_num ()
  365. {
  366.         scan_int();
  367.         if (cur_val < 0 || cur_val > 255) {
  368.                 print_err("Bad character code");
  369.                 help_char();
  370.                 int_error(cur_val);
  371.                 cur_val = 0;
  372.         }
  373. }
  374.  
  375. scan_fifteen_bit_int ()
  376. {
  377.         scan_int();
  378.         if (cur_val < 0 || cur_val > 077777) {
  379.                 print_err("Bad math code");
  380.                 help_mathchar();
  381.                 int_error(cur_val);
  382.                 cur_val = 0;
  383.         }
  384. }
  385.  
  386. scan_twenty_seven_bit_int ()
  387. {
  388.         scan_int();
  389.         if (cur_val < 0 || cur_val> 0777777777) {
  390.                 print_err("Bad delimiter code");
  391.                 help_del();
  392.                 int_error(cur_val);
  393.                 cur_val = 0;
  394.         }
  395. }
  396.  
  397. #define get_nbsx_token() \
  398.         {negative = FALSE; \
  399.         do {get_nbx_token(); \
  400.                 if (cur_tok == MINUS_TOKEN) { \
  401.                         negative = !negative; \
  402.                         cur_tok = PLUS_TOKEN;} \
  403.         } while (cur_tok == PLUS_TOKEN);}
  404.  
  405. scan_int ()
  406. {
  407.         int             d;
  408.         val             m;
  409.         bool    vacuous;
  410.         bool    negative;
  411.         bool    OK_so_far;
  412.  
  413.         d = 0;
  414.         radix = 0;
  415.         OK_so_far = TRUE;
  416.         get_nbsx_token();
  417.         if (cur_tok == ALPHA_TOKEN) {
  418.                 get_token();
  419.                 if (cur_tok < CS_TOKEN_FLAG) {
  420.                         cur_val = cur_chr;
  421.                         if (cur_cmd <= RIGHT_BRACE) {
  422.                                 if (cur_cmd == RIGHT_BRACE)
  423.                                         incr(align_state);
  424.                                 else decr(align_state);
  425.                         }
  426.                 } else if (cur_tok < CS_TOKEN_FLAG + SINGLE_BASE)
  427.                         cur_val = cur_tok - CS_TOKEN_FLAG - ACTIVE_BASE;
  428.                 else cur_val = cur_tok - CS_TOKEN_FLAG - SINGLE_BASE;
  429.                 if (cur_val > 127) {
  430.                         print_err("Improper alphabetic constant");
  431.                         help_char_const();
  432.                         cur_val = 0;
  433.                         back_error();
  434.                 } else scan_optional_space();
  435.         } else if (cur_cmd >= MIN_INTERNAL && cur_cmd <= MAX_INTERNAL)
  436.                 scan_something_internal(INT_VAL, FALSE);
  437.         else {
  438.                 radix = 10;
  439.                 m = 214748364;
  440.                 if (cur_tok == OCTAL_TOKEN) {
  441.                         radix = 8;
  442.                         m = 02000000000;
  443.                         get_x_token();
  444.                 } else if (cur_tok == HEX_TOKEN) {
  445.                         radix = 16;
  446.                         m = 010000000000;
  447.                         get_x_token();
  448.                 }
  449.                 vacuous = TRUE;
  450.                 cur_val = 0;
  451.                 loop {
  452.                         if (cur_tok < ZERO_TOKEN + radix &&
  453.                                 cur_tok >= ZERO_TOKEN &&
  454.                                 cur_tok <= ZERO_TOKEN + 9)
  455.                                 d = cur_tok - ZERO_TOKEN;
  456.                         else if (radix == 16) {
  457.                                 if (cur_tok <= A_TOKEN + 5 && cur_tok >= A_TOKEN)
  458.                                         d = cur_tok - A_TOKEN + 10;
  459.                                 else if (cur_tok <= OTHER_A_TOKEN + 5 &&
  460.                                         cur_tok >= OTHER_A_TOKEN)
  461.                                         d = cur_tok - OTHER_A_TOKEN + 10;
  462.                                 else break;
  463.                         } else break;
  464.                         vacuous = FALSE;
  465.                         if      (cur_val >= m && (cur_val > m || d > 7 || radix != 10)) {
  466.                                 if (OK_so_far) {
  467.                                         print_err("Number too big"); 
  468.                                         help_big_num();
  469.                                         error();
  470.                                         cur_val = INFINITY;
  471.                                         OK_so_far = FALSE;
  472.                                 }
  473.                         } else cur_val = cur_val * radix + d;
  474.                         get_x_token();
  475.                 }
  476.                 if (vacuous) {
  477.                         print_err("Missing number, treated as zero");
  478.                         help_missing_number();
  479.                         back_error();
  480.                 } else if (cur_cmd != SPACER)
  481.                         back_input();
  482.         }
  483.         if (negative)
  484.                 negate(cur_val);
  485. }       
  486.         
  487. #define set_conversion(NUM, DENOM) \
  488.         {num = NUM; denom = DENOM;}
  489.  
  490. scan_dimen (mu, inf, shortcut)
  491.         bool    mu;
  492.         bool    inf;
  493.         bool    shortcut;
  494. {
  495.         val             f;
  496.         int             k;
  497.         scal    v;
  498.         val             num;
  499.         val             denom;
  500.         bool    negative;
  501.         val             save_cur_val;
  502.  
  503.         f = 0;
  504.         negative = FALSE;
  505.         arith_error = FALSE;
  506.         cur_order = NORMAL;
  507.         if (!shortcut) {
  508.                 get_nbsx_token();
  509.                 if (cur_cmd >= MIN_INTERNAL && cur_cmd <= MAX_INTERNAL) {
  510.                         if (mu) {
  511.                                 scan_something_internal(MU_VAL, FALSE);
  512.                                 if (cur_val_level >= GLUE_VAL) {
  513.                                         v = width(cur_val);
  514.                                         delete_glue_ref(cur_val);
  515.                                         cur_val = v;
  516.                                 }
  517.                                 if (cur_val_level == MU_VAL)
  518.                                         goto attach_sign;
  519.                                 if (cur_val_level != INT_VAL)
  520.                                         mu_error();
  521.                         } else {
  522.                                 scan_something_internal(DIMEN_VAL, FALSE);
  523.                                 if (cur_val_level == DIMEN_VAL)
  524.                                         goto attach_sign;
  525.                         }
  526.                 } else {
  527.                         back_input();
  528.                         if (cur_tok == EURO_POINT_TOKEN)
  529.                                 cur_tok = POINT_TOKEN;
  530.                         if (cur_tok != POINT_TOKEN)
  531.                                 scan_int();
  532.                         else {
  533.                                 radix = 10;
  534.                                 cur_val = 0;
  535.                         }
  536.                         if (cur_tok == EURO_POINT_TOKEN)
  537.                                 cur_tok = POINT_TOKEN;
  538.                         if (radix == 10 && cur_tok == POINT_TOKEN) {
  539.                                 k = 0;
  540.                                 get_token();
  541.                                 loop {
  542.                                         get_x_token();
  543.                                         if (cur_tok > ZERO_TOKEN + 9 || cur_tok < ZERO_TOKEN)
  544.                                                 break;
  545.                                         if (k < 17) {
  546.                                                 dig[k] = cur_tok - ZERO_TOKEN;
  547.                                                 incr(k);
  548.                                         }
  549.                                 }
  550.                                 f = round_decimals(k);
  551.                                 if (cur_cmd != SPACER)
  552.                                         back_input();
  553.                         }
  554.                 }
  555.         }
  556.         if (cur_val < 0) {
  557.                 negative = !negative;
  558.                 negate(cur_val);
  559.         }
  560.         if (inf) {
  561.                 if (scan_keyword("fil")) {
  562.                         cur_order = FIL;
  563.                         while (scan_keyword("l")) {
  564.                                 if (cur_order == FILLL) {
  565.                                         print_err("Illegal unit of measure (");
  566.                                         print("replaced by filll)");
  567.                                         help_filll();
  568.                                         error();
  569.                                 } else incr(cur_order);
  570.                         }
  571.                         goto attach_fraction;
  572.                 }
  573.         }
  574.         save_cur_val = cur_val;
  575.         get_nbx_token();
  576.         if (cur_cmd < MIN_INTERNAL || cur_cmd > MAX_INTERNAL)
  577.                 back_input();
  578.         else {
  579.                 if (mu) {
  580.                         scan_something_internal(MU_VAL, FALSE);
  581.                         if (cur_val_level >= GLUE_VAL) {
  582.                                 v = width(cur_val);
  583.                                 delete_glue_ref(cur_val);
  584.                                 cur_val = v;
  585.                         }
  586.                         if (cur_val_level != MU_VAL)
  587.                                 mu_error();
  588.                 } else scan_something_internal(DIMEN_VAL, FALSE);
  589.                 v = cur_val;
  590.                 goto found;
  591.         }
  592.         if (mu)
  593.                 goto not_found;
  594.         if (scan_keyword("em"))
  595.                 v = quad(cur_font);
  596.         else if (scan_keyword("ex"))
  597.                 v = x_height(cur_font);
  598.         else goto not_found;
  599.         scan_optional_space();
  600.  
  601. found:
  602.         cur_val = nx_plus_y(save_cur_val, v, xn_over_d(v, f, 0200000L));
  603.         goto attach_sign;
  604.  
  605. not_found:
  606.         if (mu)  {
  607.                 if (scan_keyword("mu"))
  608.                         goto attach_fraction;
  609.                 else {
  610.                         print_err("Illegal unit of measure (");
  611.                         print("mu inserted)");
  612.                         help_mu();
  613.                         error();
  614.                         goto attach_fraction;
  615.                 }
  616.         }
  617.         if (scan_keyword("true")) {
  618.                 prepare_mag();
  619.                 if (mag != 1000) {
  620.                         cur_val = xn_over_d(cur_val, 1000L, mag);
  621.                         f = (1000 * f + 0200000 * remainder) / mag;
  622.                         cur_val += f / 0200000;
  623.                         f %= 0200000;
  624.                 }
  625.         }
  626.         if (scan_keyword("pt"))
  627.                 goto attach_fraction;
  628.         if (scan_keyword("in")) {set_conversion(7227, 100);}
  629.         else if (scan_keyword("pc")) {set_conversion(12, 1);}
  630.         else if (scan_keyword("cm")) {set_conversion(7227, 254);}
  631.         else if (scan_keyword("mm")) {set_conversion(7227, 2540);}
  632.         else if (scan_keyword("bp")) {set_conversion(7227, 7200);}
  633.         else if (scan_keyword("dd")) {set_conversion(1238, 1157);}
  634.         else if (scan_keyword("cc")) {set_conversion(14856, 1157);}
  635.         else if (scan_keyword("sp")) goto done;
  636.         else {
  637.                 print_err("Illegal unit of measure (");
  638.                 print("pt inserted)");
  639.                 help_dimen();
  640.                 error();
  641.                 goto attach_fraction;
  642.         }
  643.         cur_val = xn_over_d(cur_val, num, denom);
  644.         f = (num * f + 0200000 * remainder) / denom;
  645.         cur_val += f / 0200000;
  646.         f %= 0200000;
  647.  
  648. attach_fraction:
  649.         if (cur_val >= 0400000)
  650.                 arith_error = TRUE;
  651.         else cur_val = cur_val * UNITY + f;
  652.  
  653. done:
  654.         scan_optional_space();
  655.  
  656. attach_sign:
  657.         if (arith_error || abs(cur_val) >= 010000000000) {
  658.                 print_err("Dimension too large");
  659.                 help_big_dimen();
  660.                 error();
  661.                 cur_val = MAX_DIMEN;
  662.                 arith_error = FALSE;
  663.         }
  664.         if (negative)
  665.                 negate(cur_val);
  666. }
  667.  
  668. scan_glue (level)
  669.         int             level;
  670. {
  671.         ptr             q;
  672.         bool    mu;
  673.         bool    negative;
  674.  
  675.         mu = (level == MU_VAL);
  676.         get_nbsx_token();
  677.         if (cur_cmd >= MIN_INTERNAL && cur_cmd <= MAX_INTERNAL) {
  678.                 scan_something_internal(level, negative);
  679.                 if (cur_val_level >= GLUE_VAL) {
  680.                         if (cur_val_level != level)
  681.                                 mu_error();
  682.                         return;
  683.                 }
  684.                 if (cur_val_level == INT_VAL)
  685.                         scan_dimen(mu, FALSE, TRUE);
  686.                 else if (level == MU_VAL)
  687.                         mu_error();
  688.         } else {
  689.                 back_input();
  690.                 scan_dimen(mu, FALSE, FALSE);
  691.                 if (negative)
  692.                         negate(cur_val);
  693.         }
  694.         q = new_spec(zero_glue);
  695.         width(q) = cur_val;
  696.         if (scan_keyword("plus")) {
  697.                 scan_dimen(mu, TRUE, FALSE);
  698.                 stretch(q) = cur_val;
  699.                 stretch_order(q) = cur_order;
  700.         }
  701.         if (scan_keyword("minus")) {
  702.                 scan_dimen(mu, TRUE, FALSE);
  703.                 shrink(q) = cur_val;
  704.                 shrink_order(q) = cur_order;
  705.         }
  706.         cur_val = q;
  707. }
  708.  
  709. ptr
  710. scan_rule_spec ()
  711. {
  712.         ptr             q;
  713.  
  714.         q = new_rule();
  715.         if (cur_cmd == VRULE)
  716.                 width(q) = DEFAULT_RULE;
  717.         else {
  718.                 height(q) = DEFAULT_RULE;
  719.                 depth(q) = 0;
  720.         }
  721.  
  722. reswitch:
  723.         if (scan_keyword("width")) {
  724.                 scan_normal_dimen();
  725.                 width(q) = cur_val;
  726.                 goto reswitch;
  727.         }
  728.         if (scan_keyword("height")) {
  729.                 scan_normal_dimen();
  730.                 height(q) = cur_val;
  731.                 goto reswitch;
  732.         }
  733.         if (scan_keyword("depth")) {
  734.                 scan_normal_dimen();
  735.                 depth(q) = cur_val;
  736.                 goto reswitch;
  737.         }
  738.         return q;
  739. }
  740.  
  741. /*
  742.  *      Help text
  743.  */
  744.  
  745. help_mathchar ()
  746. {
  747.         help2("A numeric math code must be between 0 and 32767.",
  748.         "I changed this one to zero.");
  749. }
  750.  
  751. help_number ()
  752. {
  753.         help2("Since I expected to read a number between 0 and 15,",
  754.         "I changed this one to zero.");
  755. }
  756.  
  757. help_char ()
  758. {
  759.         help2("The numeric code for a character must be between 0 and 127.",
  760.         "I changed this one to zero.");
  761. }
  762.  
  763. help_char_num ()
  764. {
  765.       help2("A character number must be between 0 and 255.",
  766.       "I changed this one to zero.");
  767. }
  768.  
  769. help_char_const ()
  770. {
  771.         help2("A one-character control sequence belongs after a ` mark.",
  772.         "So I'm essentially inserting \\0 here.");
  773. }
  774.  
  775. help_big_num ()
  776. {
  777.         help2("I can only go up to 2147483647 = 017777777777 = 0x7FFFFFFF.",
  778.         "so I'm using that number instead of yours.");
  779. }
  780.  
  781. help_missing_number ()
  782. {
  783.         help3("A number should have been here; I inserted `0'.",
  784.         "(If you can't figure out why I needed to see a number,",
  785.         "look up `weird error' in the index to The TeXbook.)");
  786. }
  787.  
  788. help_filll ()
  789. {
  790.         help1("I dddon't go any higher than filll.");
  791. }
  792.  
  793. help_mu ()
  794. {
  795.         help4("The unit of measurement in math glue must be mu.",
  796.         "To recover gracefully from this error, it's best to",
  797.         "delete the erroneous units; e.g., type `2' to delete",
  798.         "two letters. (See Chapter 27 of The TeXbook.)");
  799. }
  800.  
  801. help_mu_error ()
  802. {
  803.         help1("I'm going to assume that 1mu=1pt when they're mixed.");
  804. }
  805.  
  806. help_dimen ()
  807. {
  808.         help6("Dimensions can be in units of em, ex, in, pt, pc,",
  809.         "cm, mm, dd, cc, bp, or sp; but yours is a new one!",
  810.         "I'll assume that you meant to say pt, for printers' points.",
  811.         "To recover gracefully from this error, it's best to",
  812.         "delete the erroneous units; e.g. type `2' to delete",
  813.         "two letters. (See Chapter 27 of The TeXbook.)");
  814. }
  815.         
  816. help_big_dimen ()
  817. {
  818.         help2("I can't work with sizes bigger than about 19 feet.",
  819.         "Continue and I'll use the largest value I can.");
  820. }
  821.  
  822. help_thee ()
  823. {
  824.         help1("I'm forgetting what you said and using zero instead.");
  825. }
  826.  
  827. help_left ()
  828. {
  829.         help4("A left brace was mandatory here, so I've put one in.",
  830.         "You might want to delete and/or insert some corrections",
  831.         "so that I will find a matching right brace soon.",
  832.         "If you're confused by all this, try typing `I}' now.")
  833. }
  834.  
  835. help_aux ()
  836. {
  837.         help4("You can refer to \\spacefactor only in horizontal mode;",
  838.         "you can refer to \\prevdepth only in vertical mode; and",
  839.         "neither of these is meaningful inside \\write. So",
  840.         "I'm forgetting what you said and using zero instead.");
  841. }
  842.  
  843. help_del ()
  844. {
  845.         help2("A numeric delimiter code must be between 0 and 2^{27}-1.",
  846.         "I changed this one to zero.");
  847. }
  848.  
  849. help_reg ()
  850. {
  851.         help2("A register number must be between 0 and 255.",
  852.               "I changed this one to zero.");
  853. }
  854.